#include<iostream>
#include <functional>
#include <memory>
#include <unordered_map>
#include <vector>
#include <unistd.h>
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimeTask
{
public:
    TimeTask(uint64_t id,uint32_t timeout,const TaskFunc &task):_id(id),_timeout(timeout),_task(task),_check(false)
    {}
    ~TimeTask()
    {
        if(_check==false)_task();//当没有被取消时被执行
        _release();
    }
    void SetRelease(const ReleaseFunc &cb){_release=cb;}
    void Cancel(){_check=true;}
    uint32_t TimeOut() {return _timeout;}
private:
    uint64_t _id;
    uint32_t _timeout;//超时时间
    TaskFunc _task;
    ReleaseFunc _release;
    bool _check;
};

class TimeWheel
{
public:
    using PtrFunc = std::shared_ptr<TimeTask>;
    using WeakFunc = std::weak_ptr<TimeTask>;
    TimeWheel():_tick(0),_capcity(60),_wheel(_capcity){}
    //添加定时任务
    void TimerAdd(uint64_t id,uint32_t timeout,const TaskFunc &task)
    {
        //先构建一个对象
        PtrFunc pt(new TimeTask(id,timeout,task));
        pt->SetRelease(std::bind(&TimeWheel::RemoveTimers,this,id));
        //将该任务添加到wheel
        _wheel[(pt->TimeOut()+_tick)%_capcity].push_back(pt);
        _timers[id]=WeakFunc(pt);//直接构建一个weak_ptr防止循环引用
    }
    //刷新/延长超时时间
    void TimerRefresh(uint64_t id)
    {
        //通过保存的WeakFunc对象构造一个PtrFunc对象
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;
        }
        PtrFunc pt = it->second.lock();
        //重新添加到任务中
         _wheel[(pt->TimeOut()+_tick)%_capcity].push_back(pt);
    }
    void TimerCancel(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it == _timers.end())
        {
            return;
        }
        PtrFunc pt = it->second.lock();
        if(pt) pt->Cancel();
    }
    //这个函数每次执行一次，_tick就加1
    void RunTimerTask()
    {
        _tick=(_tick+1)%_capcity;
        _wheel[_tick].clear();
    }
private:
    void RemoveTimers(uint64_t id)
    {
        auto it = _timers.find(id);
        if(it != _timers.end())
        {
            _timers.erase(id);
        }
    }
private:
    int _tick;//当前时间轮的指向
    int _capcity;//最大超时时间
    std::vector<std::vector<PtrFunc>> _wheel;
    std::unordered_map<uint64_t,WeakFunc> _timers;//用来存储任务id与任务的映射关系，这样在时钟指到该任务时就能快速找到该任务
};

class Test
{
public:
    Test(){std::cout<<"构造"<<std::endl;}
    ~Test(){std::cout<<"析构"<<std::endl;}
};
void Delete(Test * t)
{
    delete t;
}
int main()
{
    TimeWheel tw;
    Test* t = new Test();
    tw.TimerAdd(888,5,std::bind(Delete,t));
    for(int i = 0;i<5;i++)
    {
        sleep(1);
        tw.TimerRefresh(888);
        std::cout<<"刷新了一个定时任务，5秒钟后执行"<<std::endl;
        tw.RunTimerTask();
    }
    tw.TimerCancel(888);
    std::cout<<"定时任务已取消"<<std::endl;
    while(1)
    {
        sleep(1);
        tw.RunTimerTask();
    }
    return 0;
}